﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO.Ports;
using Newtonsoft.Json;
using uPLibrary.Networking.M2Mqtt;

namespace tsInput.libs
{

    public class TInput
    {
        public byte pgkSOH = (byte)1;
        public byte pgkEOT = (byte)4;
        public byte pgkSTX = (byte)2;
        public byte pgkDLE = (byte)16;
        public byte pgkDC3 = (byte)19;
        public byte pgkDC4 = (byte)20;
        public byte cmdRF_Time = (byte)82;
        public byte cmdO2_Set = (byte)79;
        public byte cmdKA_Score = (byte)75;

        String code = "fets01";
        int lightRed = 0;
        int lightGreen = 0;
        int lightWhite = 0;
        int lightW = 0;
        int setIndex = 0;
        String currentTm = "";
        int scoreLeft = 0;
        int flagLeft = 0;
        int flagRedLeft = 0;
        int flagYelloLeft = 0;
        int scoreRight = 0;
        int flagRight = 0;
        int flagRedRight = 0;
        int flagYelloRight = 0;
        int winFlag = 0;

        protected bool isReady = false;

        public String Code
        {
            get { return code; }
            set
            {
                code = value;
            }
        }
        public int LightRed
        {
            get
            {
                return lightRed;
            }
            set
            {
                if (lightRed != value)
                {
                    lightRed = value;
                    triggerDataChangeEvent("lightRed");
                }
            }
        }
        public int LightGreen
        {
            get
            {
                return lightGreen;
            }
            set
            {
                if (lightGreen != value)
                {
                    lightGreen = value;
                    triggerDataChangeEvent("lightGreen");
                }
            }
        }
        public int LightWhite
        {
            get
            {
                return lightWhite;
            }
            set
            {
                if (lightWhite != value)
                {
                    lightWhite = value;
                    triggerDataChangeEvent("lightWhite");
                }
            }
        }
        public int LightW
        {
            get
            {
                return lightW;
            }
            set
            {
                if (lightW != value)
                {
                    lightW = value;
                    triggerDataChangeEvent("lightW");
                }
            }
        }
        public String CurrentTime
        {
            get
            {
                return currentTm;
            }
            set
            {
                if (currentTm != value)
                {
                    currentTm = value;
                    triggerTimeChangeEvent(currentTm);
                }
            }
        }
        public int SetIndex
        {
            get
            {
                return setIndex;
            }
            set
            {
                if (setIndex != value)
                {
                    setIndex = value;
                    triggerDataChangeEvent("setIndex");
                }
            }
        }
        public int ScoreLeft
        {
            get
            {
                return scoreLeft;
            }
            set
            {
                if (scoreLeft != value)
                {
                    scoreLeft = value;
                    triggerDataChangeEvent("scoreLeft");
                }
            }
        }
        public int FlagLeft
        {
            get
            {
                return flagLeft;
            }
            set
            {
                if (flagLeft != value)
                {
                    flagLeft = value;
                    triggerDataChangeEvent("flagLeft");
                }
            }
        }
        public int FlagRedLeft
        {
            get
            {
                return flagRedLeft;
            }
            set
            {
                if (flagRedLeft != value)
                {
                    flagRedLeft = value;
                    triggerDataChangeEvent("flagRedLeft");
                }
            }
        }
        public int FlagRedRight
        {
            get
            {
                return flagRedRight;
            }
            set
            {
                if (flagRedRight != value)
                {
                    flagRedRight = value;
                    triggerDataChangeEvent("flagRedRight");
                }
            }
        }
        public int ScoreRight
        {
            get
            {
                return scoreRight;
            }
            set
            {
                if (scoreRight != value)
                {
                    scoreRight = value;
                    triggerDataChangeEvent("scoreRight");
                }
            }
        }
        public int FlagRight
        {
            get
            {
                return flagRight;
            }
            set
            {
                if (flagRight != value)
                {
                    flagRight = value;
                    triggerDataChangeEvent("flagRight");
                }
            }
        }
        public int FlagYelloLeft
        {
            get
            {
                return flagYelloLeft;
            }
            set
            {
                if (flagYelloLeft != value)
                {
                    flagYelloLeft = value;
                    triggerDataChangeEvent("flagYelloLeft");
                }
            }
        }
        public int FlagYelloRight
        {
            get
            {
                return flagYelloRight;
            }
            set
            {
                if (flagYelloRight != value)
                {
                    flagYelloRight = value;
                    triggerDataChangeEvent("flagYelloRight");
                }
            }
        }
        public int WinFlag
        {
            get
            {
                return winFlag;
            }
            set
            {
                if (winFlag != value)
                {
                    winFlag = value;
                    triggerDataChangeEvent("winFlag");
                }
            }
        }
        public Dictionary<String, object> getDict()
        {
            Dictionary<String, object> dt = new Dictionary<string, object>();
            try
            {
                dt.Add("Code", Code);
                dt.Add("LightRed", LightRed);
                dt.Add("LightGreen", LightGreen);
                dt.Add("LightWhite", LightWhite);
                dt.Add("LightW", LightW);
                dt.Add("CurrentTime", CurrentTime);
                dt.Add("SetIndex", SetIndex);
                dt.Add("ScoreLeft", ScoreLeft);
                dt.Add("FlagLeft", FlagLeft);
                dt.Add("FlagRedLeft", FlagRedLeft);
                dt.Add("FlagYelloLeft", FlagYelloLeft);
                dt.Add("ScoreRight", ScoreRight);
                dt.Add("FlagRight", FlagRight);
                dt.Add("FlagRedRight", FlagRedRight);
                dt.Add("FlagYelloRight", FlagYelloRight);
                dt.Add("WinFlag", WinFlag);
            }
            catch (Exception er)
            {
                Console.WriteLine("json error");
            }
            return dt;
        }
        public String ToJson()
        {
            String res = "{}";
            try
            {
                Dictionary<String, object> dt = getDict();
                res = Newtonsoft.Json.JsonConvert.SerializeObject(dt);
            }
            catch (Exception er)
            {
                Console.WriteLine("json error");
            }
            return res;
        }

        public virtual void open() { }
        public virtual void close() { }

        void triggerDataChangeEvent(String dataKey)
        {
            if (this.onDataChange != null)
            {
                try
                {
                    if (isReady)
                    {
                        this.onDataChange(this, dataKey);
                    }
                }
                catch (Exception er)
                {
                    Console.WriteLine("tiggerDataChangeEvent error");
                }
            }
        }
        void triggerTimeChangeEvent(String newTime)
        {
            if (this.onTimeChange != null)
            {
                try
                {
                    if (isReady)
                    {
                        this.onTimeChange(this, newTime);
                    }
                }
                catch (Exception er)
                {
                    Console.WriteLine("triggerTimeChangeEvent error");
                }
            }
        }

        public eventHandler_OnDataChange onDataChange;
        public eventHandler_OnTimeChange onTimeChange;
        public EventHandler onReady;

    }

    public delegate void eventHandler_OnDataChange(object sender, String dataKey);
    public delegate void eventHandler_OnTimeChange(object sender, String newTime);

    public class TInput01 : TInput
    {
        SerialPort sp = new SerialPort();


        object lockObj = new object();


        public String serComm = "COM3";
        public int serBaudRate = 9600;
        public Parity serParity = Parity.None;
        public int serDataBits = 8;
        public StopBits serStopBits = StopBits.One;

        public bool IsOpenned
        {
            get
            {
                bool flag = sp != null ? sp.IsOpen : false;
                return flag;
            }
        }

        public override void open()
        {
            try
            {
                this.isReady = false;
                this.close();
                sp = new SerialPort();
                sp.PortName = serComm;
                sp.BaudRate = serBaudRate;
                sp.Parity = serParity;
                sp.DataBits = serDataBits;
                sp.StopBits = serStopBits;
                sp.DataReceived += recData;
                sp.Open();
                System.Threading.Thread.Sleep(2000);
                isReady = IsOpenned;
                if (onReady != null)
                {
                    onReady(this, null);
                }
            }
            catch (Exception er)
            {
                Console.WriteLine("open comm error.");
            }
        }
        public override void close()
        {
            try
            {
                isReady = false;
                beginRec = false;
                if (sp != null)
                {
                    sp.Close();
                }
            }
            catch (Exception er)
            {
                Console.WriteLine("close comm error.");
            }
        }
        bool beginRec = false;
        List<byte> dataBuf = new List<byte>();
        void recData(object sender, SerialDataReceivedEventArgs en)
        {
            lock (lockObj)
            {
                try
                {
                    try
                    { 
                        int len = sp.BytesToRead;
                        byte[] bts = new byte[len];
                        sp.Read(bts, 0, len);
                        for (int i = 0; i < bts.Length; i++)
                        {
                            byte data = bts[i];
                            if (beginRec)
                            {
                                if (data == pgkSOH)
                                {
                                    dataBuf.Clear();
                                }
                                else if (data == pgkEOT)
                                {
                                    if (dataBuf.Count > 0)
                                    {
                                        setPgkBody(dataBuf.ToArray());
                                        dataBuf.Clear();
                                    }

                                }
                                else
                                {
                                    dataBuf.Add(data);
                                }


                            }
                            else
                            {
                                if (data == pgkEOT)
                                {
                                    beginRec = true;
                                }
                            }


                        }

                    }
                    catch (Exception eer)
                    {
                        Console.WriteLine("recData error.");
                    }
                }
                catch (Exception ee)
                {
                    Console.WriteLine("recData lock error.");
                }
            }
        }
        void setPgkBody(byte[] pgkBody)
        {
            try
            {
                int offSet = 0;
                if (pgkBody != null && pgkBody.Length > 0)
                {
                    byte ac = pgkBody[0];
                    //Console.WriteLine("action:" + ac.ToString());
                    if (ac == pgkDC4)
                    {
                        offSet += 2;
                        LightRed = pgkBody[offSet] - (byte)48;
                        offSet += 2;
                        LightGreen = pgkBody[offSet] - (byte)48;
                        offSet += 2;
                        LightWhite = pgkBody[offSet] - (byte)48;
                        offSet += 2;
                        LightW = pgkBody[offSet] - (byte)48;
                        //Console.WriteLine("light...");
                    }
                    else if (ac == pgkDC3)
                    {
                        int stxPos = -1;
                        for (int i = 0; i < pgkBody.Length; i++)
                        {
                            if (pgkBody[i] == pgkSTX)
                            {
                                stxPos = i;
                                break;
                            }
                        }
                        //Console.WriteLine("STX-POS:" + stxPos.ToString()+".cmd->"+ pgkBody[1].ToString());
                        if (stxPos > 0)
                        {
                            if (pgkBody[1] == cmdRF_Time)
                            {
                                offSet = pgkBody.Length - 10;
                                String tm = Encoding.ASCII.GetString(pgkBody, offSet, 10);
                                tm = System.Text.RegularExpressions.Regex.Replace(tm.Trim(), " ", "");
                                CurrentTime = tm;
                                //Console.WriteLine("time:" + tm);
                                //Console.WriteLine("-----------------------------------------------------");
                            }
                            else if (pgkBody[1] == cmdO2_Set)
                            {
                                offSet = pgkBody.Length - 3;
                                String strSet = Encoding.ASCII.GetString(pgkBody, offSet, 3);
                                strSet = System.Text.RegularExpressions.Regex.Replace(strSet.Trim(), " ", "");
                                int setInd = int.Parse(strSet);
                                SetIndex = setInd;
                                //Console.WriteLine("set:" + setInd.ToString());
                            }
                            else if (pgkBody[1] == cmdKA_Score)
                            {
                                offSet = stxPos + 1;
                                String strData = Encoding.ASCII.GetString(pgkBody, offSet, pgkBody.Length - offSet);
                                strData = System.Text.RegularExpressions.Regex.Replace(strData.Trim(), " ", "");
                                String[] arrs = strData.Split(new char[] { '/' });
                                String[] arrLeft = arrs[0].Split(new char[] { ':' });
                                String[] arrRight = arrs[1].Split(new char[] { ':' });
                                WinFlag = int.Parse(arrs[2]);
                                ScoreLeft = int.Parse(arrLeft[0]);
                                FlagLeft = int.Parse(arrLeft[1]);
                                ScoreRight = int.Parse(arrRight[0]);
                                FlagRight = int.Parse(arrRight[1]);

                                //Console.WriteLine("score." );
                            }

                        }
                        else
                        {
                            //Console.WriteLine("other...");
                        }

                    }
                }


            }
            catch (Exception er)
            {
                Console.WriteLine("setPgkBody error.");
            }
        }
    }

    public class TInput02 : TInput
    {
        SerialPort sp = new SerialPort();

        object lockObj = new object();


        public String serComm = "COM6";
        public int serBaudRate = 38400;
        public Parity serParity = Parity.None;
        public int serDataBits = 8;
        public StopBits serStopBits = StopBits.One;

        public bool IsOpenned
        {
            get
            {
                bool flag = sp != null ? sp.IsOpen : false;
                return flag;
            }
        }

        public override void open()
        {
            try
            {
                this.isReady = false;
                this.close();
                this.isReady = false;
                this.close();
                sp = new SerialPort();
                sp.PortName = serComm;
                sp.BaudRate = serBaudRate;
                sp.Parity = serParity;
                sp.DataBits = serDataBits;
                sp.StopBits = serStopBits;
                sp.DataReceived += recData;
                sp.Open();
                System.Threading.Thread.Sleep(2000);
                isReady = IsOpenned;
                if (onReady != null)
                {
                    onReady(this, null);
                }
            }
            catch (Exception er)
            {
                Console.WriteLine("open comm error.");
            }
        }
        public override void close()
        {
            try
            {
                isReady = false;
                if (sp != null)
                {
                    sp.Close();
                }
            }
            catch (Exception er)
            {
                Console.WriteLine("close comm error.");
            }
        }
        bool beginRec = false;
        List<byte> dataBuf = new List<byte>(); 
        void recData(object sender, SerialDataReceivedEventArgs en)
        {
            lock (lockObj)
            {
                try
                {
                    try
                    {
                        int len = sp.BytesToRead;
                        byte[] bts = new byte[len];
                        sp.Read(bts, 0, len);
                        for (int i = 0; i < bts.Length; i++)
                        {
                            byte data = bts[i];
                            if (beginRec)
                            {
                                if (data == pgkSOH)
                                {
                                    dataBuf.Clear();
                                }
                                else if (data == pgkEOT)
                                {
                                    if (dataBuf.Count > 0)
                                    {
                                        setPgkBody(dataBuf.ToArray());
                                        dataBuf.Clear();
                                    }

                                }
                                else
                                {
                                    dataBuf.Add(data);
                                }


                            }
                            else
                            {
                                if (data == pgkEOT)
                                {
                                    beginRec = true;
                                }
                            } 
                        }

                    }
                    catch (Exception eer)
                    {
                        Console.WriteLine("recData error.");
                    }
                }
                catch (Exception ee)
                {
                    Console.WriteLine("recData lock error.");
                }
            }
        }
        void setPgkBody(byte[] pgkBody)
        {
            try
            {
                bool isData = pgkBody != null && pgkBody.Length > 10 && pgkBody[0] == (byte)0x13 && pgkBody[1] == (byte)0x44; //01 13 44
                bool isTime = pgkBody != null && pgkBody.Length > 10 && pgkBody[0] == (byte)0x13 && pgkBody[1] == (byte)0x4E; //01 13 4e
                bool isLight = pgkBody != null && pgkBody.Length > 5 && pgkBody[0] == (byte)0x14 && pgkBody[1] == (byte)0x52; //01 R
                int offSet = 0;
                if (isData) {
                    //13 44 02 30 32 3A 30 34 02 30 31 30 31 30 02 30 30 30 31 30 02 31 02 32 02 33 33 
                    //D 03:07 00010 01010 2 2 33
                    offSet = 3;
                    String pgkStr = Encoding.ASCII.GetString(pgkBody, offSet, pgkBody.Length - offSet);
                    String[] arrs = pgkStr.Split(new char[] { (char)2 });
                    String[] scoreArr = arrs[0].Split(new char[] { ':' });
                    ScoreLeft = int.Parse(scoreArr[0]);
                    ScoreRight = int.Parse(scoreArr[1]);
                    String flagStr = arrs[1].Substring(0, 2);
                    FlagYelloLeft = flagStr == "00" ? 0 : 1;
                    flagStr = arrs[1].Substring(3);
                    FlagRedLeft = flagStr == "00" ? 0 : 1;
                    flagStr = arrs[2].Substring(0, 2);
                    FlagYelloRight = flagStr == "00" ? 0 : 1;
                    flagStr = arrs[2].Substring(3);
                    FlagRedRight = flagStr == "00" ? 0 : 1;
                    SetIndex = int.Parse(arrs[4]);
                }
                else if (isTime)
                {
                    //13 4E 02 30 32 3A 35 35 2E 20 20
                    //N02:54.  
                    offSet = 3;
                    String pgkStr = Encoding.ASCII.GetString(pgkBody, offSet, pgkBody.Length - offSet);
                    pgkStr = pgkStr.Trim();
                    CurrentTime = pgkStr;
                }
                else if (isLight)
                {
                    //14 52 30 47 30 57 30 77 30
                    //R0G0W0w0  
                    offSet = 2;
                    LightRed = pgkBody[offSet] >  0x30 ? 1 : 0;
                    offSet += 2;
                    LightGreen = pgkBody[offSet] > 0x30 ? 1 : 0;
                    offSet += 2;
                    LightWhite = pgkBody[offSet] > 0x30 ? 1 : 0;
                    offSet += 2;
                    LightW = pgkBody[offSet] > 0x30 ? 1 : 0;
                }

            }
            catch (Exception er)
            {
                Console.WriteLine("setPgkBody error.");
            }
        }

    }

    public class TMqClient
    {
        public TMqClient() { }
        public TMqClient(String svr, int port, String userName, String pwd)
        {
            mqSvr = svr;
            mqPort = port;
            mqUserName = userName;
            mqPwd = pwd;
        }
        public String mqSvr = "dq.hhdata.cn";
        public int mqPort = 42024;
        public String mqUserName = "admin";
        public String mqPwd = "Hhuc1115";
        public String clientId = "";
        public String notifyTopic = "/fe2023";
        public MqttClient client = null;
        public bool isConnected
        {
            get
            {
                bool flag = false;
                if (client != null)
                {
                    flag = client.IsConnected;
                }
                return flag;
            }
        }
        public void connect()
        {
            try
            {
                close();
                String _clientId = Guid.NewGuid().ToString();
                client = new MqttClient(mqSvr, Convert.ToInt32(mqPort), false, null, null, MqttSslProtocols.None);
                client.Connect(clientId, mqUserName, mqPwd);
                if (isConnected)
                {
                    clientId = _clientId;
                }

            }
            catch (Exception er)
            {
                Console.Write("connect mq error.");
            }
        }
        public void close()
        {
            try
            {
                clientId = "";
                if (client != null)
                {
                    if (client.IsConnected)
                    {
                        client.Disconnect();
                    }
                    client = null;
                }
            }
            catch (Exception er)
            {
                Console.Write("close mq error.");
            }
        }
        public void send(String topic, String data)
        {
            try
            {
                if (isConnected)
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(data);
                    client.Publish(topic, bytes, 0, false);
                }
            }
            catch (Exception er)
            {
                Console.Write("close mq error.");
            }
        }
    }
}
